stringFuncs.toSmartCase   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
cc 1
eloc 3
c 2
b 1
f 0
nc 1
nop 0
dl 0
loc 4
rs 10
1
/** global: UB */
2
3
// CASING
4
5
// PROVIDES THE TABLES USED FOR FAST CASE-INSENSITIVE STRING COMPARISON
6
// FOR THESE TABLES SEE "unicode uppercase lowercase tables.xlsx"
7
8
// meta tables
9
UB.UTF_casingRangedLowerS = [97, 224, 1072, 1121, 1169, 1377, 4304, 7681, 7841, 9424];
10
UB.UTF_casingRangedLowerE = [122, 246, 1103, 1153, 1215, 1414, 4341, 7829, 7929, 9449];
11
UB.UTF_casingRangedIncrement = [1, 1, 1, 2, 2, 1, 1, 2, 2, 1];
12
UB.UTF_casingRangedUpper = [65, 192, 1040, 1120, 1168, 1329, 4256, 7680, 7840, 9398];
13
14
// raw tables
15
UB.UTF_casingRawLower = [248, 249, 250, 251, 252, 253, 254, 255, 257, 259, 261, 263, 265, 267, 269, 271, 273, 275, 277, 279, 281, 283, 285, 287, 289, 291, 293, 295, 297, 299, 301, 303, 305, 307, 309, 311, 314, 316, 318, 320, 322, 324, 326, 328, 331, 333, 335, 337, 339, 341, 343, 345, 347, 349, 351, 353, 355, 357, 359, 361, 363, 365, 367, 369, 371, 373, 375, 378, 380, 382, 387, 389, 392, 396, 402, 409, 417, 419, 421, 424, 429, 432, 436, 438, 441, 445, 454, 457, 460, 462, 464, 466, 468, 470, 472, 474, 476, 479, 481, 483, 485, 487, 489, 491, 493, 495, 499, 501, 507, 509, 511, 513, 515, 517, 519, 521, 523, 525, 527, 529, 531, 533, 535, 595, 596, 599, 600, 601, 603, 608, 611, 616, 617, 623, 626, 629, 643, 648, 650, 651, 658, 940, 941, 942, 943, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 995, 997, 999, 1001, 1003, 1005, 1007, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116, 1118, 1119, 1218, 1220, 1224, 1228, 1233, 1235, 1237, 1239, 1241, 1243, 1245, 1247, 1249, 1251, 1253, 1255, 1257, 1259, 1263, 1265, 1267, 1269, 1273, 7936, 7937, 7938, 7939, 7940, 7941, 7942, 7943, 7952, 7953, 7954, 7955, 7956, 7957, 7968, 7969, 7970, 7971, 7972, 7973, 7974, 7975, 7984, 7985, 7986, 7987, 7988, 7989, 7990, 7991, 8000, 8001, 8002, 8003, 8004, 8005, 8017, 8019, 8021, 8023, 8032, 8033, 8034, 8035, 8036, 8037, 8038, 8039, 8064, 8065, 8066, 8067, 8068, 8069, 8070, 8071, 8080, 8081, 8082, 8083, 8084, 8085, 8086, 8087, 8096, 8097, 8098, 8099, 8100, 8101, 8102, 8103, 8112, 8113, 8144, 8145, 8160, 8161];
16
UB.UTF_casingRawUpper = [216, 217, 218, 219, 220, 221, 222, 376, 256, 258, 260, 262, 264, 266, 268, 270, 272, 274, 276, 278, 280, 282, 284, 286, 288, 290, 292, 294, 296, 298, 300, 302, 73, 306, 308, 310, 313, 315, 317, 319, 321, 323, 325, 327, 330, 332, 334, 336, 338, 340, 342, 344, 346, 348, 350, 352, 354, 356, 358, 360, 362, 364, 366, 368, 370, 372, 374, 377, 379, 381, 386, 388, 391, 395, 401, 408, 416, 418, 420, 423, 428, 431, 435, 437, 440, 444, 452, 455, 458, 461, 463, 465, 467, 469, 471, 473, 475, 478, 480, 482, 484, 486, 488, 490, 492, 494, 497, 500, 506, 508, 510, 512, 514, 516, 518, 520, 522, 524, 526, 528, 530, 532, 534, 385, 390, 394, 398, 399, 400, 403, 404, 407, 406, 412, 413, 415, 425, 430, 433, 434, 439, 902, 904, 905, 906, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 931, 932, 933, 934, 935, 936, 937, 938, 939, 908, 910, 911, 994, 996, 998, 1000, 1002, 1004, 1006, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1038, 1039, 1217, 1219, 1223, 1227, 1232, 1234, 1236, 1238, 1240, 1242, 1244, 1246, 1248, 1250, 1252, 1254, 1256, 1258, 1262, 1264, 1266, 1268, 1272, 7944, 7945, 7946, 7947, 7948, 7949, 7950, 7951, 7960, 7961, 7962, 7963, 7964, 7965, 7976, 7977, 7978, 7979, 7980, 7981, 7982, 7983, 7992, 7993, 7994, 7995, 7996, 7997, 7998, 7999, 8008, 8009, 8010, 8011, 8012, 8013, 8025, 8027, 8029, 8031, 8040, 8041, 8042, 8043, 8044, 8045, 8046, 8047, 8072, 8073, 8074, 8075, 8076, 8077, 8078, 8079, 8088, 8089, 8090, 8091, 8092, 8093, 8094, 8095, 8104, 8105, 8106, 8107, 8108, 8109, 8110, 8111, 8120, 8121, 8152, 8153, 8168, 8169];
17
18
19
// final tables (= ranged + raw)
20
UB.UTF_casingTablesMax = 9450;
21
22
UB.initCasing = function(){
23
	
24
	// exit if already initialized
25
	if (UB.UTF_lowerToUpper != null){
26
		return;
27
	}
28
	
29
	// CALC CASING CONVERSION TABLES
30
	UB.UTF_lowerToUpper = [];
31
	UB.UTF_upperToLower = [];
32
	
33
	// init by mapping to self (most chars dont have an uppercase/lowercase version)
34
	for (var n = 0, nlast = UB.UTF_casingTablesMax;n <= nlast;n++){
35
		UB.UTF_lowerToUpper[n] = n;
36
		UB.UTF_upperToLower[n] = n;
37
	}
38
	
39
	// per range
40
	for (var r = 0, rl = UB.UTF_casingRangedLowerS.length;r<rl;r++){
41
		
42
		// per value in range
43
		var inc = UB.UTF_casingRangedIncrement[r];
44
		var offset = UB.UTF_casingRangedUpper[r] - UB.UTF_casingRangedLowerS[r];
45
		for (var lower = UB.UTF_casingRangedLowerS[r], lowerlast = UB.UTF_casingRangedLowerE[r];lower <= lowerlast;lower += inc){
46
			
47
			// calc uppercase
48
			var upper = lower + offset;
49
			
50
			// store in table
51
			UB.UTF_lowerToUpper[lower] = upper;
52
			UB.UTF_upperToLower[upper] = lower;
53
			
54
		}
55
		
56
	}
57
	
58
	// per raw value
59
	for (var n = 0, nl = UB.UTF_casingRawLower.length;n<nl;n++){
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable n already seems to be declared on line 34. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
60
		
61
		lower = UB.UTF_casingRawLower[n];
62
		upper = UB.UTF_casingRawUpper[n];
63
		
64
		// store in table
65
		UB.UTF_lowerToUpper[lower] = upper;
66
		UB.UTF_upperToLower[upper] = lower;
67
		
68
	}
69
	
70
	// fix bug in unicode table .. "I" >> "i"
71
	UB.UTF_upperToLower[73] = 105;
72
	
73
	
74
}
75
76
77
var arrayFuncs = {
78
79
	camelCaseMergeWords: function(firstCharCaps = false){
80
		var words = this;
81
		
82
		// lowercase first letter
83
		words[0] = firstCharCaps ? words[0].uppercaseFirst() : words[0].lowercaseFirst();
84
		
85
		// loop thru all words
86
		var newWords = "";
87
		for (var w = 0, wl = words.length;w<wl;w++){
88
			var word = words[w].replace(UB.regex.Trim, '');
89
			
90
			// cap first letter if not 1st word
91
			newWords += w === 0 ? word : word.uppercaseFirst();
92
		}
93
		return newWords;
94
	},
95
	
96
	none:null
97
};
98
99
// register funcs
100
UB.registerFuncs(Array.prototype, arrayFuncs);
101
102
103
var stringFuncs = {
104
	
105
	// casing
106
	camelCaseSeperate: function(){
107
		var camelCase = this;
108
		
109
		// loop thru all chars
110
		var lastUp = false;
111
		var lastSpace = false;
112
		var newName = [];
113
		var len = 0;
114
		for (var c = 0, cl = camelCase.length - 1;c <= cl;c++){
115
			var char = camelCase.charAt(c);
116
			var charNext = c < cl ? camelCase.charAt(c + 1) : "_";
117
			
118
			// if its a Capital ... and if prev is not also a capital ... or if the next is small
119
			var up = (char.toUpperCase() == char);
120
			var nextUp = (charNext.toUpperCase() == charNext);
121
			if ((up && (!lastUp || !nextUp) && !lastSpace) || char == "_") {
122
				
123
				// add a space
124
				if (len > 0 && newName[len - 1] != " "){
125
					newName.push(" ");
126
					len++;
127
				}
128
			}
129
			lastUp = up;
130
			
131
			// add the char
132
			if (char != "_"){
133
				newName.push(char);
134
				len++;
135
			}
136
			lastSpace = char == " ";
137
		}
138
		
139
		// caps first letter
140
		return newName.join("").uppercaseFirst();
141
	},
142
	camelCaseSeperateWords: function(){
143
		var camelCase = this;
144
		return camelCase.camelCaseSeperate().split(" ");
145
	},
146
	camelCaseMerge: function(firstCharCaps = false){
147
		var sentence = this;
148
		
149
		// exit quickly if no spaces .. no words to merge
150
		if (sentence.indexOf(" ") === -1) {
151
			if (firstCharCaps) {
152
				return sentence.uppercaseFirst();
153
			}
154
			return sentence;
155
		}
156
		
157
		// merge words using camel case
158
		return sentence.split(" ").camelCaseMergeWords(firstCharCaps);
159
	},
160
	uppercaseFirst: function(){
161
		var str = this;
162
		str = str.trim();
163
		return str.charAt(0).toUpperCase() + str.substr(1);
164
	},
165
	lowercaseFirst: function(){
166
		var str = this;
167
		str = str.trim();
168
		return str.charAt(0).toLowerCase() + str.substr(1);
169
	},
170
	toSmartCase: function(){
171
		var word = this;
172
		return word.toCustomCase(";,. -_" + "\t" + "\n", true);
173
	},
174
	toSentenceCase: function(){
175
		var word = this;
176
		return word.toCustomCase(".", false);
177
	},
178
	toCustomCase: function(capsAfterChars, preserveCaps = false){
179
		var word = this;
180
		var nextCaps = true;// first char caps
181
		
182
		// per char
183
		var chars = word.splitChars();
184
		var chars2 = [];
185
		for (var c = 0, cl = chars.length;c<cl;c++){
186
			var ch = chars[c];
187
			var added = false;
188
			
189
			// add as CAPS if wanted
190
			if (nextCaps) {
191
				nextCaps = false;
192
				chars2.push(ch.toUpperCase());
193
				added = true;
194
			}
195
			
196
			// next char should have caps
197
			if (capsAfterChars.indexOf(ch) > -1) {
198
				nextCaps = true;
199
			}
200
			
201
			// add normally
202
			if (!added) {
203
				
204
				// preserve caps if wanted
205
				if (preserveCaps && ch.toUpperCase() == ch) {
206
					chars2.push(ch);
207
				}else {
208
					
209
					// add as lower case
210
					chars2.push(ch.toLowerCase());
211
				}
212
			}
213
		}
214
		return chars2.join("");
215
	},
216
	toTitleCase: function(){
217
		var word = this;
218
		return word.toCustomCase(";,. -_" + "\t" + "\n", false);
219
	},
220
	toSentenceTitleCase: function(){
221
		var title = this;
222
		var parts = [];
223
		var index = 0;
224
		
225
		// create regexps
226
		var small = "(a|an|and|as|at|but|by|en|for|if|in|of|on|or|the|to|v[.]?|via|vs[.]?)";
227
		var punct = "([!\"#$%&'()*+,./:;<=>?@[\\\\\\]^_`{|}~-]*)";
228
		var r1 =  new RegExp("\\b([A-Za-z][a-z.'Õ]*)\\b", "g");
229
		var r2 =  new RegExp("[A-Za-z]\\.[A-Za-z]", "");
230
		var r3 =  new RegExp("\\b" + small + "\\b", "ig");
231
		var r4 =  new RegExp("^" + punct + small + "\\b", "ig");
232
		var r5 =  new RegExp("\\b" + small + punct + "$", "ig");
233
		var r6 =  new RegExp(" V(s?)\\. ", "ig");
234
		var r7 =  new RegExp("(['Õ])S\\b", "ig");
235
		var split =  new RegExp("[:.;?!] |(?: |^)[\"Ò]", "g");
236
		
237
		// per word in string
238
		while (true) {
239
			var m = split.exec(title);
240
			
241
			var ToLowerCase = function(x){
242
				return x.toLowerCase();
243
			}
244
			var ToUpperCaseFirst = function(x){
245
				return x.uppercaseFirst();
246
			}
247
248
			// smart capatalize
249
			parts.push( title.substring(index, m ? m.index : title.length).replace(r1, function(all) {
250
				return r2.test(all) ? all : all.uppercaseFirst();
251
			}).replace(r3, ToLowerCase).replace(r4, function (all, punct, word){
252
				return punct + word.uppercaseFirst();
253
			}).replace(r5, ToUpperCaseFirst));
254
			
255
			index = split.lastIndex;
256
			
257
			if ( m ) parts.push( m[0] );
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
258
			else break;
259
		}
260
		
261
		return parts.join("").replace(r6, " v$1. ").replace(r7, "$1s");
262
	},
263
	toCamelCase: function(){
264
		var word = this;
265
		return word.camelCaseMerge(false);
266
	},
267
	toPascalCase: function(){
268
		var word = this;
269
		return word.camelCaseMerge(true);
270
	},
271
	toURLCase: function(){
272
		var path = this;
273
		path = path.removeAll("&");
274
		path = path.removeAll("\"");
275
		path = path.removeAll("'");
276
		path = path.removeAll(",");
277
		path = path.removeAll("?");
278
		path = path.setSlash("/").replaceAll(" ", "-");	
279
		path = path.replaceAll("----", "-");
280
		path = path.replaceAll("---", "-");
281
		path = path.replaceAll("--", "-");
282
		return path.toLowerCase();
283
	},
284
	pascalToCamelCase: function(){
285
		var word = this;
286
		
287
		// no change if already begins with lowercase letter
288
		if (word.substr(0, 1).isLowercase()) {
289
			return word;
290
		}
291
		
292
		// make the first word lowercase
293
		
294
		// if >2 chars are uppercase
295
		var num = word.countStartingUppercase();
296
		if (num > 2) {	
297
			
298
			// lowercase all uppercase chars (except the last)
299
			return word.lowercaseFirstX(num - 1);
300
		}
301
		
302
		// lowercase first char only
303
		return word.lowercaseFirst();
304
	},
305
	uppercaseFirstX: function(numOfChars){
306
		var text = this;
307
		return text.setRange(0, numOfChars - 1, text.range(0, numOfChars - 1).toUpperCase());
308
	},
309
	lowercaseFirstX: function(numOfChars){
310
		var text = this;
311
		return text.setRange(0, numOfChars - 1, text.range(0, numOfChars - 1).toLowerCase());
312
	},
313
	none:null
314
};
315
316
// register funcs
317
UB.registerFuncs(String.prototype, stringFuncs);